package com.bianmaba.spring.boot.autoconfig;

import com.bianmaba.spring.data.jpa.configure.EnableJpaRepositoriesExtension;
import com.bianmaba.spring.data.jpa.repository.support.ExtendedRepositoryImpl;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.query.QueryLookupStrategy;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableJpaRepositoriesExtension()
@SpringBootApplication
public @interface SpringBootApplicationExtension {
    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "value")
    String[] value() default {};

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "basePackages")
    String[] basePackages() default {};

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "basePackageClasses")
    Class<?>[] basePackageClasses() default {};

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "includeFilters")
    ComponentScan.Filter[] includeFilters() default {};

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "excludeFilters")
    ComponentScan.Filter[] excludeFilters() default {};

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "repositoryImplementationPostfix")
    String repositoryImplementationPostfix() default "Impl";

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "namedQueriesLocation")
    String namedQueriesLocation() default "";

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "queryLookupStrategy")
    QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;


    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "repositoryBaseClass")
    Class<?> repositoryBaseClass() default ExtendedRepositoryImpl.class;

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "repositoryFactoryBeanClass")
    Class<?> repositoryFactoryBeanClass() default JpaRepositoryFactoryBean.class;

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "entityManagerFactoryRef")
    String entityManagerFactoryRef() default "entityManagerFactory";

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "transactionManagerRef")
    String transactionManagerRef() default "transactionManager";

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "considerNestedRepositories")
    boolean considerNestedRepositories() default false;

    @AliasFor(annotation = EnableJpaRepositoriesExtension.class, attribute = "enableDefaultTransactions")
    boolean enableDefaultTransactions() default true;

    /**
     * Exclude specific auto-configuration classes such that they will never be applied.
     *
     * @return the classes to exclude
     */
    @AliasFor(annotation = SpringBootApplication.class)
    Class<?>[] exclude() default {};

    /**
     * Exclude specific auto-configuration class names such that they will never be
     * applied.
     *
     * @return the class names to exclude
     * @since 1.3.0
     */
    @AliasFor(annotation = SpringBootApplication.class)
    String[] excludeName() default {};

    /**
     * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
     * for a type-safe alternative to String-based package names.
     *
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = SpringBootApplication.class)
    String[] scanBasePackages() default {};

    /**
     * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
     * scan for annotated components. The package of each class specified will be scanned.
     * <p>
     * Consider creating a special no-op marker class or interface in each package that
     * serves no purpose other than being referenced by this attribute.
     *
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = SpringBootApplication.class)
    Class<?>[] scanBasePackageClasses() default {};
}
